import { ethers } from 'ethers'
import db, { generateId } from '../db/database.js'
import cron from 'node-cron'
import { USDT_PRECISION, USDT_DECIMALS } from '../config.js'

// 配置
const ETH_RPC_URL = process.env.ETH_RPC_URL || 'https://eth.llamarpc.com'
const BSC_RPC_URL = process.env.BSC_RPC_URL || 'https://bsc.llamarpc.com'
const ETH_USDT_CONTRACT_ADDRESS = process.env.ETH_USDT_CONTRACT_ADDRESS || '0xdAC17F958D2ee523a2206206994597C13D831ec7'
const BSC_USDT_CONTRACT_ADDRESS = process.env.BSC_USDT_CONTRACT_ADDRESS || '0x55d398326f99059fF775485246999027B3197955'

// 统一转换余额：直接除以 USDT_PRECISION
function normalizeBalance(value, currency = 'USDT') {
  if (value === null || value === undefined) return 0
  if (typeof value !== 'number') {
    value = parseFloat(value)
    if (isNaN(value)) return 0
  }
  
  if (currency === 'USDT') {
    // 所有 USDT 金额都除以 USDT_PRECISION
    return value / USDT_PRECISION
  }
  
  return value
}

// 创建providers
const ethProvider = new ethers.JsonRpcProvider(ETH_RPC_URL)
const bscProvider = new ethers.JsonRpcProvider(BSC_RPC_URL)

// 获取provider和合约地址
function getProvider(chain = 'ETH') {
  return chain === 'BSC' ? bscProvider : ethProvider
}

function getUSDTContractAddress(chain = 'ETH') {
  return chain === 'BSC' ? BSC_USDT_CONTRACT_ADDRESS : ETH_USDT_CONTRACT_ADDRESS
}

// USDT合约ABI（ERC20标准）
const USDT_ABI = [
  'function balanceOf(address owner) view returns (uint256)',
  'function transfer(address to, uint256 amount) returns (bool)',
  'event Transfer(address indexed from, address indexed to, uint256 value)'
]

// 生成钱包地址
export async function generateWalletAddress(currency = 'USDT') {
  // 生成新的钱包
  const wallet = ethers.Wallet.createRandom()
  
  // 加密私钥（实际应用中应该使用更强的加密）
  const encryptedPrivateKey = wallet.privateKey // 简化处理，实际应该加密存储

  return {
    address: wallet.address,
    privateKey: wallet.privateKey,
    encryptedPrivateKey // 应该加密后存储
  }
}

// 获取余额
export async function getBalance(address, currency = 'USDT', chain = 'ETH') {
  try {
    const provider = getProvider(chain)
    
    if (currency === 'USDT') {
      // 获取USDT余额
      const contractAddress = getUSDTContractAddress(chain)
      const contract = new ethers.Contract(contractAddress, USDT_ABI, provider)
      const balance = await contract.balanceOf(address)
      // 使用 USDT_PRECISION 作为转换因子：balance / USDT_PRECISION
      // 例如：如果 USDT_PRECISION = 100000000000，那么 1013 / 100000000000 = 0.000000001013
      // balance 可能是 BigNumber，需要转换为字符串再转换为数字
      const balanceStr = balance.toString()
      const balanceNum = Number(balanceStr)
      return balanceNum / USDT_PRECISION
    } else if (currency === 'ETH' || currency === 'BNB') {
      // 获取ETH或BNB余额
      const balance = await provider.getBalance(address)
      return parseFloat(ethers.formatEther(balance))
    }
    return 0
  } catch (error) {
    console.error(`获取余额失败 (${chain}):`, error)
    return 0
  }
}

// 监控交易
const monitoringAddresses = new Map() // address_chain -> { userId, currency, chain, lastBlock }

export function monitorTransactions(address, userId, currency, chain = 'ETH') {
  // 统一地址格式
  const normalizedAddress = address.toLowerCase()
  // 使用特殊分隔符避免地址中包含下划线导致分割错误
  const key = `${normalizedAddress}::${chain}`
  
  if (monitoringAddresses.has(key)) {
    console.log(`⏭️ 地址 ${normalizedAddress} (${chain}) 已在监控中`)
    return // 已经在监控中
  }

  monitoringAddresses.set(key, {
    userId,
    currency,
    chain,
    lastBlock: 0
  })

  console.log(`✅ 开始监控地址: ${normalizedAddress} (用户: ${userId}, 币种: ${currency}, 链: ${chain})`)
}

// 检查地址的新交易（导出供手动调用）
export async function checkAddressTransactions(address, userId, currency, chain = 'ETH') {
  try {
    // 统一地址格式为小写
    const normalizedAddress = address.toLowerCase()
    // 使用特殊分隔符避免地址中包含下划线导致分割错误
    const key = `${normalizedAddress}::${chain}`
    
    const provider = getProvider(chain)
    const contractAddress = getUSDTContractAddress(chain)
    const contract = new ethers.Contract(contractAddress, USDT_ABI, provider)
    
    // 获取当前区块号
    const currentBlock = await provider.getBlockNumber()
    
    // 获取监控信息（使用标准化地址查找）
    let monitorInfo = monitoringAddresses.get(key)
    if (!monitorInfo) {
      console.log(`⚠️ 地址 ${normalizedAddress} (${chain}) 不在监控列表中，尝试添加到监控列表`)
      // 如果不在监控列表中，先添加到监控列表
      monitorTransactions(address, userId, currency, chain)
      monitorInfo = monitoringAddresses.get(key)
      if (!monitorInfo) {
        console.log(`❌ 无法添加地址到监控列表`)
        return
      }
    }
    
    // 从上次检查的区块开始，或者从最近1000个区块开始（RPC节点限制最多1000个区块）
    const fromBlock = monitorInfo.lastBlock > 0 
      ? monitorInfo.lastBlock + 1 
      : Math.max(0, currentBlock - 1000)
    
    // 如果区块范围超过1000，需要分批查询
    const MAX_BLOCK_RANGE = 1000
    const blockRange = currentBlock - fromBlock
    
    console.log(`\n🔍 [检查交易] 地址: ${address}`)
    console.log(`   用户ID: ${userId}, 币种: ${currency}, 链: ${chain}`)
    console.log(`   区块范围: ${fromBlock} - ${currentBlock} (共 ${blockRange} 个区块)`)
    console.log(`   上次检查区块: ${monitorInfo.lastBlock}`)
    
    // 监听Transfer事件（转入该地址的交易）
    // Transfer(from, to, value) - 第二个参数是接收地址
    const filter = contract.filters.Transfer(null, normalizedAddress)
    console.log(`   过滤条件: Transfer事件，接收地址=${normalizedAddress}`)
    console.log(`   合约地址: ${contractAddress} (${chain})`)
    console.log(`   RPC节点: ${chain === 'BSC' ? BSC_RPC_URL : ETH_RPC_URL}`)
    
    let allEvents = []
    
    if (blockRange > MAX_BLOCK_RANGE) {
      // 需要分批查询
      console.log(`⚠️ 区块范围超过 ${MAX_BLOCK_RANGE}，将分批查询`)
      let startBlock = fromBlock
      
      while (startBlock <= currentBlock) {
        const endBlock = Math.min(startBlock + MAX_BLOCK_RANGE - 1, currentBlock)
        console.log(`  📦 查询区块范围: ${startBlock} - ${endBlock}`)
        
        try {
          const batchEvents = await contract.queryFilter(filter, startBlock, endBlock)
          allEvents = allEvents.concat(batchEvents)
          console.log(`  ✅ 找到 ${batchEvents.length} 个事件`)
        } catch (batchError) {
          console.error(`  ❌ 查询区块 ${startBlock}-${endBlock} 失败:`, batchError.message)
          // 继续查询下一批
        }
        
        startBlock = endBlock + 1
        
        // 避免请求过快，稍微延迟
        if (startBlock <= currentBlock) {
          await new Promise(resolve => setTimeout(resolve, 100))
        }
      }
    } else {
      // 单次查询
      allEvents = await contract.queryFilter(filter, fromBlock, currentBlock)
    }
    
    const events = allEvents
    
    console.log(`📊 找到 ${events.length} 个 Transfer 事件`)
    
    for (const event of events) {
      try {
        const txHash = event.transactionHash || event.hash
        
        // ethers v6 中事件参数访问方式
        // event.args 可能是数组或对象
        let from, to, valueArg
        if (Array.isArray(event.args)) {
          from = event.args[0]
          to = event.args[1]
          valueArg = event.args[2]
        } else if (event.args && typeof event.args === 'object') {
          from = event.args.from || event.args[0]
          to = event.args.to || event.args[1]
          valueArg = event.args.value || event.args[2]
        } else {
          console.error(`无法解析事件参数:`, event)
          continue
        }
        
        // 统一地址格式
        const normalizedTo = to.toLowerCase()
        const normalizedFrom = from.toLowerCase()
        
        // 解析金额：使用 USDT_PRECISION 作为转换因子
        // 例如：如果 USDT_PRECISION = 100000000000，那么 1013 / 100000000000 = 0.000000001013
        const value = Number(valueArg) / USDT_PRECISION
        
        console.log(`📝 处理交易: ${txHash}, 从 ${normalizedFrom} 到 ${normalizedTo}, 金额: ${value} ${currency}`)
      
      // 检查交易是否已记录
      const existingTx = db.prepare('SELECT id FROM transactions WHERE tx_id = ?').get(txHash)
      
        if (existingTx) {
          console.log(`⏭️ 交易 ${txHash} 已存在，跳过`)
          continue
        }
        
        // 确认是转入该地址的交易
        if (normalizedTo === normalizedAddress && value > 0) {
          
        // 记录充值交易
          const txId = generateId()
          
          try {
            console.log(`\n💰 [充值检测] 发现新充值交易:`)
            console.log(`   交易哈希: ${txHash}`)
            console.log(`   用户ID: ${userId}`)
            console.log(`   币种: ${currency}`)
            console.log(`   金额: ${value} ${currency}`)
            console.log(`   从地址: ${normalizedFrom}`)
            console.log(`   到地址: ${normalizedTo}`)
            console.log(`   区块号: ${event.blockNumber}`)
            
            // 先检查钱包是否存在
            const walletCheck = db.prepare('SELECT id, balance FROM wallets WHERE user_id = ? AND currency = ? AND chain = ?').get(userId, currency, chain)
            if (!walletCheck) {
              console.error(`❌ 钱包不存在: 用户 ${userId} 的 ${currency} (${chain}) 钱包不存在，无法记录充值`)
              continue
            }
            
            // 统一转换数据库余额（如果存储的是原始值）
            const currentDbBalance = normalizeBalance(walletCheck.balance || 0, currency)
            console.log(`   当前数据库余额 (原始值): ${walletCheck.balance || 0}, 转换后: ${currentDbBalance} ${currency}`)
            
            // 记录充值交易
            try {
        db.prepare(`
                INSERT INTO transactions (id, tx_id, user_id, type, currency, chain, amount, from_address, to_address, status, block_number, created_at, updated_at)
                VALUES (?, ?, ?, 'deposit', ?, ?, ?, ?, ?, 'confirmed', ?, datetime('now'), datetime('now'))
              `).run(txId, txHash, userId, currency, chain, value, normalizedFrom, normalizedTo, event.blockNumber)
              console.log(`   ✅ 交易记录已保存 (ID: ${txId}, 链: ${chain})`)
            } catch (insertError) {
              // 如果是唯一约束错误，说明交易已存在
              if (insertError.message && insertError.message.includes('UNIQUE constraint')) {
                console.log(`   ⏭️ 交易 ${txHash} 已存在，跳过`)
                continue
              }
              throw insertError
            }
            
            // 更新钱包余额（使用转换后的余额相加，然后存储标准值）
            const newBalance = currentDbBalance + value
            const updateResult = db.prepare('UPDATE wallets SET balance = ?, updated_at = datetime(\'now\') WHERE user_id = ? AND currency = ? AND chain = ?').run(newBalance, userId, currency, chain)
            
            if (updateResult.changes === 0) {
              console.error(`❌ 更新钱包余额失败: 用户 ${userId} 的 ${currency} (${chain}) 钱包不存在`)
            } else {
              console.log(`   ✅ 余额已更新: ${newBalance} ${currency} (从 ${currentDbBalance} 增加 ${value} ${currency})`)
              
              // 同步查询链上实际余额，确保数据一致性
              try {
                const actualBalance = await getBalance(address, currency, chain)
                const wallet = db.prepare('SELECT * FROM wallets WHERE user_id = ? AND currency = ? AND chain = ?').get(userId, currency, chain)
                if (wallet && Math.abs(wallet.balance - actualBalance) > 0.0001) {
                  console.log(`   ⚠️ 余额不一致，同步中... 数据库: ${wallet.balance}, 链上: ${actualBalance}`)
                  db.prepare('UPDATE wallets SET balance = ?, updated_at = datetime(\'now\') WHERE user_id = ? AND currency = ? AND chain = ?').run(actualBalance, userId, currency, chain)
                  console.log(`   ✅ 余额已同步: ${actualBalance} ${currency}`)
                } else {
                  console.log(`   ✅ 余额一致: ${wallet.balance} ${currency}`)
                }
              } catch (balanceError) {
                console.error(`   ❌ 查询链上余额失败:`, balanceError)
              }
            }
            
            // 更新监控信息的最后检查区块
            monitorInfo.lastBlock = event.blockNumber
            
            console.log(`✅ [充值完成] ${value} ${currency} 已到账到地址 ${address}`)
            console.log(`   交易哈希: ${txHash}, 区块: ${event.blockNumber}\n`)
          } catch (dbError) {
            console.error(`❌ 保存交易记录失败:`, dbError)
            console.error(`   错误详情:`, dbError.message)
            console.error(`   错误堆栈:`, dbError.stack)
          }
        } else {
          console.log(`⚠️ 交易 ${txHash} 不是转入该地址的交易 (to: ${normalizedTo}, target: ${normalizedAddress}, value: ${value})`)
        }
      } catch (eventError) {
        console.error(`处理事件失败:`, eventError)
      }
    }
    
    // 更新最后检查的区块号
    if (currentBlock > monitorInfo.lastBlock) {
      monitorInfo.lastBlock = currentBlock
    }
    
    console.log(`✅ 地址 ${address} 检查完成，最后检查区块: ${monitorInfo.lastBlock}`)
  } catch (error) {
    console.error(`❌ 检查地址 ${address} 的交易失败:`, error)
    console.error('错误详情:', error.message)
    console.error('错误堆栈:', error.stack)
  }
}

// 定期检查所有监控地址的交易
cron.schedule('*/1 * * * *', async () => {
  // 每分钟检查一次
  console.log(`\n⏰ [${new Date().toISOString()}] 开始定期检查所有监控地址...`)
  console.log(`📋 当前监控地址数量: ${monitoringAddresses.size}`)
  
  for (const [key, info] of monitoringAddresses.entries()) {
    // key格式: address::chain
    const [address] = key.split('::')
    await checkAddressTransactions(address, info.userId, info.currency, info.chain)
  }
  
  console.log(`✅ 定期检查完成\n`)
})

// 发送交易
export async function sendTransaction(fromPrivateKey, toAddress, amount, currency = 'USDT', chain = 'ETH') {
  try {
    const provider = getProvider(chain)
    const wallet = new ethers.Wallet(fromPrivateKey, provider)
    
    if (currency === 'USDT') {
      // 发送USDT
      const contractAddress = getUSDTContractAddress(chain)
      const contract = new ethers.Contract(contractAddress, USDT_ABI, wallet)
      const amountWei = ethers.parseUnits(amount.toString(), USDT_DECIMALS) // USDT小数位数从环境变量配置的精度计算
      
      const tx = await contract.transfer(toAddress, amountWei)
      return tx.hash
    } else if (currency === 'ETH' || currency === 'BNB') {
      // 发送ETH或BNB
      const amountWei = ethers.parseEther(amount.toString())
      const tx = await wallet.sendTransaction({
        to: toAddress,
        value: amountWei
      })
      return tx.hash
    }
  } catch (error) {
    console.error(`发送交易失败 (${chain}):`, error)
    throw error
  }
}

export { ethProvider as provider, ethProvider, bscProvider }

